package com.agileboot.attendance.domain.project;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.agileboot.attendance.domain.project.dto.ProjectDTO;
import com.agileboot.attendance.domain.project.dto.ProjectOptionDTO;
import com.agileboot.attendance.domain.project.dto.ProjectQuery;
import com.agileboot.attendance.domain.project.dto.ProjectRequest;
import com.agileboot.attendance.domain.project.entity.AttProjectEntity;
import com.agileboot.attendance.domain.project.model.ProjectModel;
import com.agileboot.attendance.domain.project.model.ProjectModelFactory;
import com.agileboot.attendance.domain.project.db.service.AttProjectService;
import com.agileboot.attendance.domain.order.db.AttOrderService;
import com.agileboot.attendance.domain.order.entity.AttOrderEntity;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.common.core.page.PageDTO;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 项目应用服务
 * 
 * @author ruoyi
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ProjectApplicationService {

    private final AttProjectService projectService;
    private final ProjectModelFactory projectModelFactory;
    private final AttOrderService orderService;

    /**
     * 分页查询项目列表
     * 
     * @param query 查询条件
     * @return 分页结果
     */
    public PageDTO<ProjectDTO> getProjectList(ProjectQuery query) {
        // 构建查询条件并执行分页查询
        LambdaQueryWrapper<AttProjectEntity> queryWrapper = query.buildQueryWrapper();
        Page<AttProjectEntity> entityPage = projectService.page(query.toPage(), queryWrapper);
        
        // 转换为DTO
        List<ProjectDTO> records = new ArrayList<>();
        if (CollUtil.isNotEmpty(entityPage.getRecords())) {
            for (AttProjectEntity entity : entityPage.getRecords()) {
                records.add(ProjectDTO.fromEntity(entity));
            }
        }
        
        // 创建一个新的Page对象，用于存储DTO列表
        Page<ProjectDTO> dtoPage = new Page<>();
        dtoPage.setRecords(records);
        dtoPage.setTotal(entityPage.getTotal());
        dtoPage.setCurrent(entityPage.getCurrent());
        dtoPage.setSize(entityPage.getSize());
        
        // 使用Page构造函数创建PageDTO
        return new PageDTO<>(dtoPage);
    }

    /**
     * 获取项目详情
     * 
     * @param projectId 项目ID
     * @return 项目DTO
     */
    public ProjectDTO getProjectDetail(Long projectId) {
        AttProjectEntity entity = projectService.getById(projectId);
        if (entity == null || entity.getDeleted()) {
            throw new ApiException(ErrorCode.Business.PROJECT_OBJECT_NOT_FOUND, projectId);
        }
        
        return ProjectDTO.fromEntity(entity);
    }

    /**
     * 新增项目
     * 
     * @param request 请求参数
     * @return 项目ID
     */
    @Transactional(rollbackFor = Exception.class)
    public Long addProject(ProjectRequest request) {
        // 检查项目名称是否已存在
        AttProjectEntity existingProject = projectService.getByProjectName(request.getProjectName());
        if (existingProject != null) {
            throw new ApiException(ErrorCode.Business.PROJECT_OBJECT_EXISTS, request.getProjectName());
        }
        
        // 创建并验证项目模型
        ProjectModel projectModel = projectModelFactory.create();
        BeanUtils.copyProperties(request, projectModel);
        projectModel.setDeleted(false); // 设置为未删除
        projectModel.validateProjectInfo(); // 验证项目信息
        
        // 保存项目
        AttProjectEntity entity = projectModel.toEntity();
        projectService.save(entity);
        
        return entity.getProjectId();
    }

    /**
     * 更新项目
     * 
     * @param request 请求参数
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateProject(ProjectRequest request) {
        // 加载项目模型
        ProjectModel projectModel = projectModelFactory.loadById(request.getProjectId());
        
        // 检查项目是否可编辑
        if (!projectModel.isEditable()) {
            throw new ApiException(ErrorCode.Business.PROJECT_NOT_EDITABLE);
        }
        
        // 检查项目名称是否已存在（排除自身）
        AttProjectEntity existingProject = projectService.getByProjectName(request.getProjectName());
        if (existingProject != null && !existingProject.getProjectId().equals(request.getProjectId())) {
            throw new ApiException(ErrorCode.Business.PROJECT_OBJECT_EXISTS, request.getProjectName());
        }
        
        // 更新项目
        BeanUtils.copyProperties(request, projectModel);
        projectModel.validateProjectInfo(); // 验证项目信息
        
        projectService.updateById(projectModel.toEntity());
    }

    /**
     * 删除项目
     * 
     * @param projectId 项目ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteProject(Long projectId) {
        // 检查项目是否存在
        ProjectModel projectModel = projectModelFactory.loadById(projectId);
        
        // 检查是否有未完成的关联订单
        LambdaQueryWrapper<AttOrderEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AttOrderEntity::getProjectId, projectId)
                .eq(AttOrderEntity::getStatus, "0") // 进行中的订单
                .eq(AttOrderEntity::getDeleted, false);
        
        long count = orderService.count(queryWrapper);
        if (count > 0) {
            throw new ApiException(ErrorCode.Business.PROJECT_HAS_ACTIVE_ORDERS, projectModel.getProjectName());
        }

        projectService.removeById(projectId);
    }

    /**
     * 导出项目
     * 
     * @param query 查询条件
     * @param response 响应对象
     */
    public void exportProject(ProjectQuery query, HttpServletResponse response) {
        try {
            // 设置响应头
            String fileName = URLEncoder.encode("项目列表", StandardCharsets.UTF_8.toString());
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            
            // 查询所有项目
            if (query == null) {
                query = new ProjectQuery();
            }
            // 获取所有数据，不分页
            query.setPageSize(-1);
            query.setPageNum(1);
            
            // 构建查询条件并执行查询
            LambdaQueryWrapper<AttProjectEntity> queryWrapper = query.buildQueryWrapper();
            List<AttProjectEntity> projectList = projectService.list(queryWrapper);
            
            // 转换为DTO
            List<ProjectDTO> projectDTOList = projectList.stream()
                .map(ProjectDTO::fromEntity)
                .collect(Collectors.toList());
            
            // 导出Excel
            EasyExcel.write(response.getOutputStream(), ProjectDTO.class)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .sheet("项目列表")
                .doWrite(projectDTOList);
        } catch (IOException e) {
            throw new ApiException(ErrorCode.Internal.INTERNAL_ERROR, "导出失败");
        }
    }

    /**
     * 导入项目
     * 
     * @param file 导入文件
     * @return 导入结果
     */
    public String importProject(MultipartFile file) {
        // TODO: 使用EasyExcel导入项目数据，类似于已实现的供应商和人员导入功能
        return "导入成功";
    }

    /**
     * 下载导入模板
     * 
     * @param response 响应对象
     */
    public void downloadImportTemplate(HttpServletResponse response) {
        try {
            // 设置响应头
            String fileName = URLEncoder.encode("项目导入模板", StandardCharsets.UTF_8.toString());
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            
            // 创建模板数据
            List<ProjectDTO> templateList = new ArrayList<>();
            ProjectDTO template = new ProjectDTO();
            template.setProjectName("上海金融信息化项目");
            template.setProjectCode("PJ001");
            template.setProjectDesc("上海金融行业信息化建设项目");
            template.setProjectManager("张三");
            template.setStatus("0"); // 规划中
            template.setTotalBudget(new BigDecimal("500000"));
            template.setTotalManMonths(new BigDecimal("24"));
            template.setRemark("示例数据，导入时请删除");
            templateList.add(template);
            
            // 导出Excel模板
            EasyExcel.write(response.getOutputStream(), ProjectDTO.class)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .sheet("项目数据")
                .doWrite(templateList);
        } catch (IOException e) {
            throw new ApiException(ErrorCode.Internal.INTERNAL_ERROR, "模板下载失败");
        }
    }

    /**
     * 获取项目下拉选项列表
     *
     * @return 项目选项列表
     */
    public List<ProjectOptionDTO> getProjectOptions() {
        return projectService.lambdaQuery()
            .eq(AttProjectEntity::getDeleted, false)
            .in(AttProjectEntity::getStatus, "0", "1") // 仅获取规划中和进行中的项目
            .list()
            .stream()
            .map(project -> new ProjectOptionDTO(
                project.getProjectId(),
                project.getProjectName(),
                project.getProjectCode(),
                project.getStatus()
            ))
            .collect(Collectors.toList());
    }
} 